/**
 * Copyright &copy; 2013-2015 山东易科德软件有限公司   All rights reserved.
 */
package cn.net.ecode.modules.msg.service;

import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.net.ecode.common.config.Global;
import cn.net.ecode.common.persistence.Page;
import cn.net.ecode.common.service.CrudService;
import cn.net.ecode.common.service.ServiceException;
import cn.net.ecode.common.utils.Reflections;
import cn.net.ecode.common.utils.SpringContextHolder;
import cn.net.ecode.common.utils.StringUtils;
import cn.net.ecode.modules.msg.dao.MessageDao;
import cn.net.ecode.modules.msg.dao.MessageRecordDao;
import cn.net.ecode.modules.msg.entity.Message;
import cn.net.ecode.modules.msg.entity.MessageRecord;
import cn.net.ecode.modules.msg.entity.MsgStatis;
import cn.net.ecode.modules.sys.dao.EmployeeDao;
import cn.net.ecode.modules.sys.dao.UserDao;
import cn.net.ecode.modules.sys.entity.User;
import cn.net.ecode.modules.sys.utils.UserUtils;

import com.google.common.collect.Lists;

/**
 * 消息管理Service
 * @author ThinkGem
 * @version 2015-5-30
 */
@Service
@Transactional(readOnly = true)
public class MessageService extends CrudService<MessageDao, Message> {

	@Autowired
	private MessageRecordDao messageRecordDao;
	@Autowired
	private UserDao userDao;
	@Autowired
	private EmployeeDao employeeDao;
	
	/**
	 * 内部消息推送服务类
	 */
	private MsgPushService msgPushService = new MsgPushService();
	
	/**
	 * 获取单条数据
	 * @param message
	 * @return
	 */
	public Message get(Message message) {
		return super.get(message);
	}

	/**
	 * 查询列表数据
	 * @param message
	 * @return
	 */
	public List<Message> findList(Message message) {
		return super.findList(message);
	}

	/**
	 * 查询分页数据
	 * @param page 分页对象
	 * @param message
	 * @return
	 */
	public Page<Message> findPage(Page<Message> page, Message message) {
		return super.findPage(page, message);
	}

	/**
	 * 保存并发送消息
	 * 	消息类型（1通知 2消息 3短信 4邮件 5微信）
	 * 	接受者类型（1用户 2部门 3角色 4岗位 5手机号 6邮件 7微信）
	 * @param message
	 */
	@Transactional(readOnly = false)
	public void save(Message message) {
		// 正常状态的消息进行保存消息记录和发送，否则只是草稿状态保存消息
		if (Message.STATUS_NORMAL.equals(message.getStatus())) {
			
			// 设置发送者和发送时间
			User user = message.getCurrentUser();
			if (user.getUserCode() == null){
				user = UserUtils.get(User.SUPER_ADMIN_CODE);
			}
			message.setSender(user.getUserCode());
			message.setSenderName(user.getUserName());
			if (message.getSendDate() == null){
				message.setSendDate(new Date());
			}
			super.save(message);

			// 保存消息记录，并推送消息
			String[] codes = StringUtils.split(message.getReceiverCodes(), ",");
			String[] names = StringUtils.split(message.getReceiverNames(), ",");
			if (names != null && codes.length != names.length){
				throw new ServiceException("消息接受者的receiverCodes和receiverNames的“,”必须相等");
			}
			if (codes != null){
				List<User> userList = Lists.newArrayList();
				// 接受者为所有用户
				if (Message.RECEIVER_ALL_USER.equals(message.getReceiverCodes())){
					userList = dao.findAllUserList(new Message());
					saveMessageRecode(message, userList);
				}else{
					// 根据接受者类型获取接受者用户
					switch (message.getReceiverType()) {
					case Message.RECEIVER_TYPE_USER:	// 用户
						userList = dao.findUserByUserCodes(new Message(codes));
						saveMessageRecode(message, userList);
						break;
					case Message.RECEIVER_TYPE_OFFICE:	// 部门
						userList = dao.findUserByOfficeCodes(new Message(codes));
						saveMessageRecode(message, userList);
						break;
					case Message.RECEIVER_TYPE_ROLE:	// 角色
						userList = dao.findUserByRoleCodes(new Message(codes));
						saveMessageRecode(message, userList);
						break;
					case Message.RECEIVER_TYPE_POST:	// 岗位
						userList = dao.findUserByPostCodes(new Message(codes));
						saveMessageRecode(message, userList);
						break;
					default:
						saveMessageRecode(message, codes, names);
						break;
					}
				}
			}
		} else {
			super.save(message);
		}

		// 如果不是内部消息，则调用消息发送服务
		if (!Message.TYPE_NOTIFY.equals(message.getType())
			&& !Message.TYPE_MESSAGE.equals(message.getType())){
			// 调用消息发送服务
			executeSeadTask();
		}
		
	}
	
	/**
	 * 保存消息记录（根据内部用户获取接受者）
	 * @param message
	 * @param userList
	 */
	private void saveMessageRecode(Message message, List<User> userList){
		MessageRecord record = null;
		for (User u : userList) {
			boolean isMsgPush = false;
			record = new MessageRecord();
			record.setMessage(message);
			// 根据消息类型设置接受者
			switch (message.getType()) {
			case Message.TYPE_MESSAGE:	// 1通知
			case Message.TYPE_NOTIFY:	// 2消息
				record.setReceiver(u.getUserCode());
				isMsgPush = true; // 如果是内部消息发送，则直接发送消息提醒
				break;
			case Message.TYPE_SMS:		// 3短信
				record.setReceiver(u.getMobile());
				break;
			case Message.TYPE_EMAIL:	// 4邮件
				record.setReceiver(u.getEmail());
				break;
			case Message.TYPE_WEIXIN:	// 5微信
//				record.setReceiver(u.getWeixin());
				break;
			}
			record.setReceiverName(u.getUserName());
			record.setStatus(MessageRecord.STATUS_UNDELIVERED);
			record.preInsert();
			messageRecordDao.insert(record);
			// 如果是内部消息发送，则直接发送消息提醒
			if (isMsgPush){
				msgPushService.sendMsg(u.getUserCode(), message, record.getId());
			}
		}
	}
	
	/**
	 * 保存消息记录（直接设置接受者，如手机，邮箱，微信号）
	 * @param message
	 * @param codes
	 * @param names
	 */
	private void saveMessageRecode(Message message, String[] codes, String[] names){
		MessageRecord record = null;
		for (int i=0; i < codes.length; i++){
			String code = codes[i];
			record = new MessageRecord();
			record.setMessage(message);
			record.setReceiver(code);
			record.setReceiverName(names == null ? code : names[i]);
			record.setStatus(MessageRecord.STATUS_UNDELIVERED);
			record.preInsert();
			messageRecordDao.insert(record);
		}
	}
	
	/**
	 * 保存消息及记录
	 * @param message
	 */
	@Transactional(readOnly = false)
	public void saveRecord(MessageRecord messageRecord) {
		// 如果消息记录不存在，则插入一条新消息记录
		if (messageRecordDao.isExists(messageRecord.getId()) == 0){
			messageRecordDao.insert(messageRecord);
		}
		// 如果消息不存在，则插入一条新消息
		Message message = messageRecord.getMessage();
		if (dao.isExists(message.getId()) == 0){
			message.setUpdateBy(message.getCurrentUser());
			message.setUpdateDate(new Date());
			message.setCreateBy(message.getUpdateBy());
			message.setCreateDate(message.getUpdateDate());
			message.setSender(message.getCreateBy().getUserCode());
			dao.insert(message);
		}
		// 调用消息发送服务
		executeSeadTask();
	}

	/**
	 * 调用实时发送服务
	 */
	private void executeSeadTask(){
		// 如果不是内部消息，并开启了实时发送消息，则执行消息发送。
		if (Global.TRUE.equals(Global.getConfig("msg.realtime.enabled"))){
			// 开启新线程，不影响主线程
			new Thread(){
				public void run() {

					// 获取消息发送服务beanName
					String beanName = Global.getConfig("msg.realtime.sendTaskBeanName");
					if (StringUtils.isNotBlank(beanName)){
						try{
							// 发送服务执行
							Object object = SpringContextHolder.getBean(beanName);
							Reflections.invokeMethod(object, "execute", null, null);
						}catch(NoSuchBeanDefinitionException ex){
							logger.error(beanName+"未实例化，请在spring-context-task.xml中开启"
									+beanName+"的注解，如果你是自定义的发送服务，请新建并实例化。", ex);
						}catch(Exception ex){
							logger.error("实时消息发送失败，服务配置不正确。", ex);
						}
					}
					
				}
			}.run();
		}
	}
	
	/**
	 * 删除数据
	 * @param message
	 */
	@Transactional(readOnly = false)
	public void delete(Message message) {
		super.delete(message);
	}

	/** 
	 * 获取消息记录
	 * @param mr
	 */
	public List<MessageRecord> findMessageRecordList(MessageRecord mr) {
		return messageRecordDao.findList(mr);
	}

	/** 
	 * 获取消息发送记录分页信息
	 * @param page
	 * @param mr
	 */
	public Page<MessageRecord> findMessageRecordPage(Page<MessageRecord> page, MessageRecord mr) {
		mr.setPage(page);
		page.setList(findMessageRecordList(mr));
		return page;

	}

	/**
	 * 更新消息记录，投递回调，读取回调
	 * @param messageRecord
	 * @return
	 */
	@Transactional(readOnly = false)
	public boolean updateMsgRecord(MessageRecord messageRecord) {
		return messageRecordDao.updateMsgRecord(messageRecord) > 0;
	}

	/**
	 * 获取统计信息，查看消息
	 * @param message
	 * @return
	 */
	public MsgStatis getMsgStatis(Message message) {
		return messageRecordDao.getMsgStatis(message);
	}
	
	/**
	 * 读取消息，查看消息
	 * @param message
	 * @param mrId
	 * @return
	 */
	@Transactional(readOnly = false)
	public Message getReadMsg(Message message, String recordId) {
		MessageRecord record = new MessageRecord();
		User u = UserUtils.getUser();
		String userCode = u.getUserCode();
		if (StringUtils.isNotBlank(recordId)) {
			record = messageRecordDao.get(new MessageRecord(recordId));
		} else {
			record.setMessage(message);
			record.setReceiver(userCode);
			record = messageRecordDao.getMessageRecord(record);
		}
//		System.out.println(record != null && userCode.equals(record.getReceiver()));
		if (record != null && userCode.equals(record.getReceiver())) {
			msgPushService.readMsg(record.getId());
		}
		return record != null && record.getMessage() != null ? dao.get(record.getMessage()) : message;
	}

}